/*****************************************
 * Copyright (C) 2018 * Ltd. All rights reserved.
 * Created date: 2018-08-02 19:18:13
 *******************************************/
#include <iostream>
#include <signal.h>
#include <execinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
 
/* include <execinfo.h> to use this macro */
#define DBG_ASSERT(x) do { \
    if (x) { break; } \
    std::cout << "###### file:" <<  __FILE__ << " line:" <<  __LINE__ << " ######" << std::endl;\
    void *pptrace_raw[32] = {0}; \
    char **pptrace_str = NULL; \
    int  trace_num = 0, iloop = 0; \
    trace_num = backtrace(pptrace_raw, 32); \
    pptrace_str = (char **)backtrace_symbols(pptrace_raw, trace_num); \
    for (iloop=0; iloop<trace_num; iloop++) { std::cout << pptrace_str[iloop] << std::endl; } \
    if (pptrace_str) { delete pptrace_str; } \
} while (0);
 
void sigsegv_test()
{
    std::cout << __func__ << " begin" << std::endl;
    char *buff = NULL;
    buff[1] = buff[1]; /* will crash here */
    std::cout << __func__ << " end" << std::endl;
}
 
void getmapsinfo()
{
    pid_t pid = getpid();
    std::string mapsfile = "/proc/";
    mapsfile.append(std::to_string(pid));
    mapsfile.append("/maps");
    std::cout << "##############################################" << std::endl;
    std::cout << "pid: " << pid << "maps: " << mapsfile << std::endl;
    int fd = open(mapsfile.c_str(), O_RDONLY);
    if (fd == -1) {
        std::cout << "open error: " << strerror(errno) << std::endl;
        return;
    }
    int len = 0;
    char buff[200] = {0};
    while ((len = read(fd, buff, sizeof(buff)-1)) > 0) {
        buff[len] = '\0';
        std::cout << buff;
    }
    std::cout << "##############################################" << std::endl;
}
 
void sigsegvhandle(int signo) {
    std::cout << "sigsegvhandle received signal: " << signo << std::endl;
    /* output callstack */
    DBG_ASSERT(0);
    getmapsinfo();
    /* reset signal handle to default */
    signal(signo, SIG_DFL);
    /* will receive SIGSEGV again and exit app */
}
 
int main() {
    /* register handler of signal SIGSEGV */
    signal(SIGSEGV, sigsegvhandle);
    sigsegv_test();
    return 0;
}
